---
title: "Custom JavaScript for Spree Storefront"
sidebarTitle: "Custom JavaScript"
description: "Learn how to add custom JavaScript to your Spree storefront"
---

## Extending Storefront with JavaScript

Spree Storefront can be easily extended with custom JavaScript. Most of the JavaScript in the storefront is powered by a framework called [Stimulus.js](https://stimulus.hotwired.dev/) which is the Ruby on Rails default. It's a very simple and minimalistic framework only enhancing our server-side rendered HTML with a bit of interactivity.

### 3rd party JavaScript libraries

Spree Storefront comes with a few 3rd party JavaScript libraries already included.

Main libraries we're using:

* [Stimulus.js](https://stimulus.hotwired.dev/)
* [Turbo](https://turbo.hotwired.dev/)
* [Swiper.js](https://swiper.com/)
* [PhotoSwipe](https://photoswipe.com/)
* [noUISlider](https://refreshless.com/nouislider/)
* [card-validator](https://github.com/braintree/card-validator) and [credit-card-type](https://github.com/braintree/credit-card-type)

You can find them in the [app/assets/javascripts/vendor](https://github.com/spree/spree/blob/main/storefront/vendor/javascript) directory.

### Managing JavaScript dependencies

You're probably wondering why these libraries are in the `vendor` directory, and not in `node_modules`.

That's because we're not using Node.js at all. So no Yarn or npm. We're using a different approach to manage dependencies.

We're using a tool called [Importmaps](https://github.com/rails/importmap-rails) to manage dependencies which is the Ruby on Rails default.

<Info>
If you want to use a different JavaScript package manager you can do so by using [jsbundling-rails](https://github.com/rails/jsbundling-rails) gem.
</Info>

#### Install dependencies

To install dependencies you need to run the following command:

```bash
bin/importmap pin react
```

This will install the dependencies, download the files to your `vendor/javascript` directory and add them to your `config/importmap.rb` file, eg.

```ruby
pin "react" # @19.1.0
```

Now you can just import the library in your application entry point, eg. `application.js`:

```js
import "react";
```

### Application entry point

Mentioned above, the application entry point is the `application.js` file. It's located in the `app/javascript` directory.

If you want to add custom JavaScript to your Spree storefront, you can do so by adding a new file to the `app/javascript` directory.

### Stimulus Controllers

Stimulus controllers are a way to add interactivity to your Spree storefront. Storefront controllers can be found in the Spree repository in the [storefront/app/javascript/spree/storefront/controllers](https://github.com/spree/spree/tree/main/storefront/app/javascript/spree/storefront/controllers) directory.

You can find more information about Stimulus controllers in the [Stimulus.js documentation](https://stimulus.hotwired.dev/handbook/controllers).

To add a new controller you need to create a new file in the `app/javascript/controllers` directory. It will be automatically picked up by the application.

```js
// app/javascript/controllers/hello_controller.js
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
  connect() {
    console.log("Hello Spree Commerce Stimulus!", this.element);
  }
}
```

To use the controller in your HTML you need to add the `data-controller` attribute to your element, eg.

```html
<div data-controller="hello">
  Hello Spree Commerce Stimulus!
</div>
```

## JavaScript snippets

If you need to add a small piece of JavaScript code (eg. tracking, marketing, analytics, customer service etc.) you can do this by:

1. Declaring a new head partial in the `config/initializers/spree.rb` file, eg.

    <Tabs>
      <Tab title="Spree 5.2+">
        ```ruby config/initializers/spree.rb
        Spree.storefront.partials.head << 'spree/shared/my_tracking_code'
        ```
      </Tab>
      <Tab title="Spree 5.1 and below">
        ```ruby config/initializers/spree.rb
        Rails.application.config.spree_storefront.head_partials << 'spree/shared/my_tracking_code'
        ```
      </Tab>
    </Tabs>

2. Creating a new file in the `app/views/spree/shared/my_tracking_code.html.erb`, where you can add your tracking code, eg.

    ```erb app/views/spree/shared/my_tracking_code.html.erb
    <script>
      console.log("I'm a spy!");
    </script>
    ```

<Info>
  Check out the [Integrations](/integrations) for existing integrations you can plug into your storefront.
</Info>

## Extending Existing Stimulus Controllers

You can extend or override existing Storefront Stimulus controllers:

```js
// app/javascript/controllers/cart_controller.js
import CartController from 'spree/storefront/controllers/cart_controller'

export default class extends CartController {
  connect() {
    super.connect()
    console.log('Extended cart controller connected!')
  }

  // Override existing method
  addItem(event) {
    // Custom logic before adding
    console.log('Adding item...')
    super.addItem(event)
    // Custom logic after adding
  }
}
```

## Turbo Events

Spree Storefront uses [Turbo](https://turbo.hotwired.dev/) for navigation. You can hook into Turbo events:

```js
// app/javascript/application.js
document.addEventListener('turbo:load', () => {
  console.log('Page loaded via Turbo')
})

document.addEventListener('turbo:before-visit', (event) => {
  console.log('About to visit:', event.detail.url)
})

document.addEventListener('turbo:frame-load', (event) => {
  console.log('Turbo frame loaded:', event.target.id)
})
```

## Related Documentation

- [Custom CSS](/developer/storefront/custom-css) - Styling your storefront
- [Sections](/developer/storefront/sections) - Creating custom sections
- [Blocks](/developer/storefront/blocks) - Creating custom blocks